package com.example.demo.common.msg;/**
 * Created by kete on 2017-12-14.
 */

import com.example.demo.common.exception.EbsException;
import com.example.demo.common.msg.disruptor.MessageEventVo;
import com.example.demo.common.msg.vo.*;
import com.example.demo.common.persistence.model.MsgRecord;
import com.example.demo.core.constant.Constants;
import com.example.demo.core.util.EntityUtil;
import com.example.demo.core.util.UserUtil;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.List;
import java.util.Map;

/**
 * 作者：kete
 * 创建时间：2017-12-14 15:01
 * 功能描述：
 * 版本：
 */
public abstract class AbstractSendMessage implements  SendMessage  {

    private Logger logger = LoggerFactory.getLogger(AbstractSendMessage.class);

    @Override
    public void send(MessageVo messageVo) {

        // 校验messageVo
        valid(messageVo);

        // 1.根据消息节点，企业设置，校验messageVo 是否需要发送,
        String nodeCode = messageVo.getMsgNodeCode();

        MessageCheckResult checkResult = check(messageVo.getAccessToken(), nodeCode);
        if(!checkResult.isNeedSend()) {
            logger.info("Org(orgId of {}) need not send {}",messageVo.getAccessToken(), nodeCode);
            return;
        }

        // 2.获取消息发送的类型（短信，邮件，站内消息等）
        List<MessageType> messageTypes  = checkResult.getMessageTypes();


        // 3.根据消息节点和消息类型，获取对应的模板，
        Map<MessageType,MessageWrapper> msgMap = fetchMessageTemplate(nodeCode,messageTypes);



        // 4.将消息模板变量和消息模板组合成消息实体
        compose(msgMap,messageVo);


        // 5.根据消息类型由不同的发送器来发送。
        dispatch(msgMap);

    }

    /**
     * 将消息派发给 各类型的消息发送器去发送
     * @param msgMap
     */
    private void dispatch(Map<MessageType, MessageWrapper> msgMap) {

        for (Map.Entry<MessageType, MessageWrapper> entry : msgMap.entrySet()) {
            MessageType key = entry.getKey();
            MessageWrapper mw = entry.getValue();

            //先加入异步队列
            mw.getReceivers().forEach((receiver)->{
                MessageSender sender = getMessageSender();
                MsgRecord r = createMsgRecord(mw);
                r.setReceiverUserId(receiver.getUserId());
                r.setReceiverUser(StringUtils.isEmpty(receiver.getEmail())?receiver.getMobile():receiver.getEmail());
                r.setMobile(receiver.getMobile());
                r.setEmail(receiver.getEmail());
                //handler.send(r,receiver,mw);
                MessageEventVo vo = new MessageEventVo(r,receiver,mw);
                sender.send(key,vo);
            });


        }

    }

    protected abstract MessageSender getMessageSender();

    //校验messageVo 数据有效性
    private void valid(MessageVo messageVo) {
        if(messageVo == null)
            throw new EbsException("common_msg_error");

    }

    private MsgRecord createMsgRecord(MessageWrapper mw) {
        MsgRecord record =new MsgRecord();
        record.setMsgTitle(mw.getTitle());
        record.setMsgContent(mw.getContent());
        record.setMsgNodeCode(mw.getMessageNodeCode());
        record.setMsgNodeName(mw.getMessageNodeName());
        record.setTodoUrl(mw.getTodoUrl());

        record.setMsgStatus("0");
        record.setIsDeleted("0");
        record.setSenderOrgId(mw.getSenderOrgId());
        record.setSenderUserId(mw.getSenderUserId());
        record.setBusinessCode(mw.getBusinessCode());
        record.setBusinessId(mw.getBusinessId());
        record.setIsRead(Constants.MSG_NO_READ);
        String token = mw.getAccessToken();
        record.setOwnerUserId(UserUtil.getUserId(token));
        EntityUtil.setValue(record,token);

        return record;
    }

    /**
     * 将模板变量跟模板组合在一起
     * @param msgMap
     */
    protected abstract void compose(Map<MessageType, MessageWrapper> msgMap, MessageVo messageVo) ;


    /**
     * 过滤用户配置，是否愿意接受消息，（注意代办和消息不允许取消订阅)
     * @param receiver
     * @return
     */
    protected abstract boolean receiverFilter(EbsMessageReceiver receiver, MessageType messageType);

    /**
     * 根据模板节点编码，模板类型获取节点模板
     * @param nodeCode
     * @param messageTypes
     * @return
     */
    protected abstract Map<MessageType,MessageWrapper> fetchMessageTemplate(String nodeCode, List<MessageType> messageTypes);


    /**
     * 根据 企业（orgId）模板节点（messageNodeCode），检查
     * @param accessToken
     * @param nodeCode
     * @return
     */
    protected abstract MessageCheckResult check(String accessToken,String nodeCode);
}
